home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung CD 2 (Tewi)(1994).iso / doc / mir / p_marc.c < prev    next >
Text File  |  1992-05-25  |  12KB  |  422 lines

  1. /*
  2.  *  SEE MIR TUTORIAL ONE, TOPIC 9.5 ... THIS IS OLD CODE THAT
  3.  *  HAS NOT BEEN UPGRADED FOR LACK OF SAMPLE DATA.
  4.  *
  5.  *  P_MARC - preprocesses Marc records to standard format.
  6.  *     See document "MARC_REC" dated June 13, 1986 by
  7.  *     Doug Lowry for detail.
  8.  *
  9.  *  written:    dblowry 31 july 86
  10.  *  modified:   dblowry 04 march 87
  11.  *          Copyright (c) 1987 Innotech Inc.
  12.  *
  13.  *  usage:  p_marc [2] filename(s)
  14.  *  or  p_marc [2]      which takes input from stdin
  15.  *      The option "2" is used to specify MARC II format,
  16.  *      which is the same as MARC except that the block and
  17.  *      record size values are omitted.
  18.  *
  19.  *  input:  mrc_fields      containing client fld identifiers
  20.  *                  and Reteaco fld nums & inv controls
  21.  *      stdin, or files
  22.  *
  23.  *  output: filename.orig  or stdout if using stdin for input
  24.  *
  25.  *  note:   this version makes use of the 4th column to specify how
  26.  *      specific fields are to be inverted and displayed.
  27.  */
  28.  
  29. #include <local.h>
  30.  
  31. #ifndef STDIO_INCLUDED
  32. #include <stdio.h>
  33. #endif
  34.  
  35. #ifndef CTYPE_INCLUDED
  36. #include <ctype.h>
  37. #endif
  38.  
  39. /*
  40.  *  declarations
  41.  */
  42.  
  43.     void    load_inv_controls(), pre_process(), parse_directory();
  44.     void    proc_field();
  45.     int get_data();
  46.  
  47. #define NUM_FLDS    999     /* max number of client fields  */
  48. #define NUM_CTLS    5       /* a safe (?) upper limit   */
  49. #define CLI_FLD_LEN_MAX 4       /* length of client supplied fld*/
  50.  
  51. #define RET_FLD_LEN 4       /* length of Reteaco fld num    */
  52. #define CTL_COL     3       /* Reteaco control column   */
  53. #define MAX_DAT_BYTES   9999        /* max bytes in record data */
  54. #define MAX_DIR_ENT 500     /* max entries in directory */
  55.  
  56. /*
  57.  *  global variables
  58.  */
  59.  
  60.     long    file_location;  /* cumulative bytes read, this file */
  61.     Bool    marcII;     /* MARC II format           */
  62.  
  63. struct _mrc_direc {
  64.     int mrc_field_num;
  65.     int mrc_field_len;
  66.     int mrc_field_offset;
  67. } direc[ MAX_DIR_ENT ];
  68.     int direc_entries;
  69.  
  70. struct _inv_ctl {
  71.     char    client_fld_id[ CLI_FLD_LEN_MAX + 1 ];
  72.     char    first_four[ NUM_CTLS ][ 4 ];
  73. } ctl[ NUM_FLDS ];
  74.  
  75.     int num_fields;
  76.  
  77.     char    data_buf[ MAX_DAT_BYTES ];
  78.  
  79. /*
  80.  *  MAIN -
  81.  */
  82.  
  83. main( argc, argv )
  84.     int argc;
  85.     char    **argv;
  86. {
  87.     int file, bgn, num_files;
  88.     char    fname[ BUFSIZ ];
  89.     FILE    *fp_in, *fp_out;
  90.  
  91.     marcII = FALSE;
  92.     if( argc > 1 && strlen( argv[ 1 ] ) == 1 && argv[1][0] == '2'
  93. )
  94.         marcII = TRUE;
  95.     num_files = argc - 1;
  96.     if( marcII )
  97.         num_files--;
  98.  
  99.     load_inv_controls();
  100.                     /* case of no files     */
  101.     if( !num_files )
  102.     {
  103.         fp_in  = stdin;
  104.         fp_out = stdout;
  105.         file_location= 0;
  106.  
  107.         pre_process( fp_out, fp_in );
  108.  
  109.         exit( 0 );
  110.     }
  111.  
  112.             /* altenately do each file on command line  */
  113.     bgn = 1;
  114.     if( marcII && num_files )
  115.         bgn = 2;
  116.     for( file = bgn; file < argc; ++file )
  117.     {
  118.         if ((fp_in = fopen( argv[ file ], "r" )) == NULL )
  119.         {
  120.               warning("%s:  file \"%s\" does not exist\n",
  121.                                  argv[ 0 ], argv[ file ] );
  122.                       continue;
  123.                 }
  124.         sprintf( fname, "%s.orig", argv[ file ] );
  125.         fp_out = fopen( fname, "w" );
  126.         file_location= 0;
  127.  
  128.         pre_process( fp_out, fp_in );
  129.  
  130.         fclose( fp_in );
  131.         fclose( fp_out );
  132.     }
  133.  
  134.     exit( 0 );
  135. }
  136.  
  137. /*
  138.  *  LOAD_INV_CONTROLS -  loads in the Reteaco field identifiers and
  139. inversion
  140.  *           control characters corresponding to client's
  141.  *           field identifiers.  The info is assumed to be in
  142.  *           the file "mrc_fields".
  143.  */
  144.  
  145.     static void
  146. load_inv_controls()
  147. {
  148.     FILE    *fp;
  149.     char    buf[ BUFSIZ ];
  150.     int i, j, col, fld;
  151.  
  152.     fp = e_fopen( "mrc_fields", "r" );
  153.  
  154.     for( fld = 0; fgets( buf, BUFSIZ, fp ) > 0; ++fld )
  155.     {
  156.                         /* client's fld id  */
  157.         for( col= 0; isalnum( buf[ col ] ) && col < CLI_FLD_LEN_MAX
  158. ;
  159.                 ++col )
  160.             ctl[ fld ].client_fld_id[ col ] = buf[ col ];
  161.         ctl[ fld ].client_fld_id[ col ] = '\0';
  162.  
  163.         for( j = col ; isspace( buf[j] ); ++j )
  164.             ;
  165.                         /* Reteaco's fld num & ctl */
  166.         for( i = 0; buf[j] != '\t'; j += RET_FLD_LEN, ++i )
  167.         {
  168.             if ( buf[ j+3 ] == '0' ) buf[ j+3 ] = ' ';
  169.             strncpy( ctl[fld].first_four[i], &buf[j], RET_FLD_LEN
  170. );
  171.             ctl[fld].first_four[ i ][ RET_FLD_LEN ] = '\0';
  172.         }
  173.         if( i < NUM_CTLS ) ctl[fld].first_four[ i ][ 0 ] = '\0';
  174.     }
  175.  
  176.     num_fields = fld;
  177.     fclose( fp );
  178.     return;
  179. }
  180.  
  181. /*
  182.  *  PRE_PROCESS - Preprocesses text from the input file and writes
  183.  *          result to supplied output file.
  184.  */
  185.  
  186.     static void
  187. pre_process( fp_out, fp_in )
  188.     FILE    *fp_out, *fp_in;
  189. {
  190.     int field;
  191.  
  192.     while( get_data( fp_in ) != EOF )
  193.     {
  194.         fputs( "000 \n", fp_out );
  195.         for( field= 0; field < direc_entries; ++field)
  196.             proc_field( field, fp_out );
  197.     }
  198.     return;
  199. }
  200.  
  201. /*
  202.  *  GET_DATA -  Pulls in block header (if needed), then record
  203. header
  204.  *      and contents.
  205.  */
  206.  
  207. #define BLK_SIZ 80
  208.  
  209.     static int
  210. get_data( fp )
  211.     FILE        *fp;
  212. {
  213.     static short    latest_block;   /* most recent block size
  214. read    */
  215.     static short    block_bytes;    /* cumulative bytes this
  216. block   */
  217.     static short    record_bytes;   /* total bytes in record    */
  218.     short       direc_bytes;    /* bytes in record directory    */
  219.     short       data_bytes; /* bytes in record data fields  */
  220.     char        leader[24];
  221.     int     four0,      /* 4 if MARC, 0 if MARC II  */
  222.             i;
  223.     short       zilch;
  224.  
  225.     four0 = 4;
  226.     if( marcII )
  227.         four0 = 0;
  228.     if ( file_location == 0 )
  229.     {
  230.         record_bytes= 0;    /* initialize once per file */
  231.         latest_block= 0;
  232.         block_bytes=  0;
  233.     }
  234.     block_bytes += record_bytes;
  235.  
  236. /*  ...If block header due to be read, attempt to evaluate it   */
  237.  
  238.     if ( !marcII && block_bytes == latest_block)
  239.     {
  240.         if(( fread( &latest_block, sizeof(short), 1, fp ) < 1 ) ||
  241.            ( fread( &zilch, sizeof(short), 1, fp ) < 1 ))
  242.             return( EOF );
  243.         if ( zilch )
  244.             error( "Block size out of sync at byte %D\n",
  245.             file_location );
  246.         block_bytes= 4;
  247.         file_location += 4;
  248.     }
  249.  
  250. /*  ...Read in the record size  */
  251.  
  252.     if( !marcII )
  253.     {
  254.         if(( fread( &record_bytes, sizeof(short), 1, fp ) < 1 ) ||
  255.            ( fread( &zilch, sizeof(short), 1, fp ) < 1 ))
  256.             error( "Failure reading record size starting\
  257.          at byte %D\n", file_location );
  258.         if ( zilch )
  259.         error( "Record size out of sync at byte %D\n",
  260.         file_location );
  261.         file_location += 4;
  262.     }
  263.  
  264. /*  Get and analyze the 24 byte marc record leader  */
  265. /*  ...Activate the commented out items below when needed.  */
  266.  
  267.     for ( i= 0; i < 24 ; i++ )
  268.     {
  269.         leader[i]= fgetc( fp );
  270.         if ( leader[i] == EOF )
  271.             return( EOF );
  272.     }
  273. /*  rec_status= leader[5];  */
  274. /*  rec_type= leader[6];    */
  275. /*  biblio_cat= leader[7];  */
  276.     leader[5]= ' ';
  277.     if( marcII )
  278.         record_bytes = atoi( leader );
  279.     else if ((atoi( &leader[0] ) + four0 ) != record_bytes)
  280.         error( "Record length inconsistent at byte %D\n",
  281.         file_location );
  282. /*  indicator_count= leader[10] - '0';  */
  283.     leader[17]= ' ';
  284.     direc_bytes= atoi( &leader[12] ) - 24;
  285.     file_location += 24;
  286.  
  287. /*  Now load the directory  */
  288.  
  289.     if ( direc_bytes > MAX_DIR_ENT * 12 ||
  290.          direc_bytes > MAX_DAT_BYTES )
  291.         error ( "Oversize directory at byte %D\n", file_location);
  292.     if ( fread( data_buf, sizeof(char), direc_bytes, fp ) <
  293. direc_bytes )
  294.         error( "Failure reading directory starting at byte %D\n",
  295.         file_location );
  296.     file_location += direc_bytes;
  297.  
  298. /*  ... and place directory into field structure    */
  299.  
  300.     if ( direc_bytes % 12 != 1 )
  301.         error( "Directory size not 12*N + 1 at byte %D\n",
  302.         file_location );
  303.     direc_entries= direc_bytes/12;
  304.     parse_directory();
  305.  
  306. /*  Now load the data stream    */
  307.  
  308.     data_bytes= record_bytes - four0 - 24 - direc_bytes;
  309.     if ( data_bytes > MAX_DAT_BYTES )
  310.         error ( "Oversize record data at byte %D\n",
  311. file_location);
  312.     if ( fread( data_buf, sizeof(char), data_bytes, fp ) <
  313. data_bytes )
  314.         error( "Failure reading record data starting at byte %D\n",
  315.         file_location );
  316.     file_location += data_bytes;
  317.  
  318.     return( 0 );
  319. }
  320.  
  321. /*
  322.  *  PARSE_DIRECTORY - Place ASCII of record directory into
  323. structure
  324.  */
  325.  
  326.     static void
  327. parse_directory()
  328. {
  329.     int entry,i;
  330.     int off;        /* offset within directory  */
  331.     char    num[4],len[5],offset[6];
  332.  
  333.     off= 0;
  334.     num[3] = len[4] = offset[5] = ' ';
  335.  
  336.     for( entry= 0; entry < direc_entries ; ++entry )
  337.     {
  338.         for( i= 0; i < 3 ; ++i )
  339.             num[ i ] = data_buf[ off++ ];
  340.         direc[entry].mrc_field_num = atoi( num );
  341.         for( i= 0; i < 4 ; ++i )
  342.             len[ i ] = data_buf[ off++ ];
  343.         direc[entry].mrc_field_len = atoi( len );
  344.         for( i= 0; i < 5 ; ++i )
  345.             offset[ i ] = data_buf[ off++ ];
  346.         direc[entry].mrc_field_offset = atoi( offset );
  347.     }
  348.     return;
  349. }
  350. /*
  351.  *  PROC_FIELD - Preprocess a single field
  352.  */
  353.  
  354.     static void
  355. proc_field( field, fpo )
  356.     int field;
  357.     FILE    *fpo;
  358. {
  359.     int low,high;   /* limits within data stream    */
  360.     int ctli, col, num, i;
  361.     char    c, nxt, four[5];
  362.  
  363.     low= direc[ field ].mrc_field_offset;
  364.     high= low + direc[ field ].mrc_field_len - 1;
  365.     num= direc[ field ].mrc_field_num - 1;
  366.     four[4] = '\0';
  367.  
  368.     for ( ctli= 0; ctli < NUM_CTLS ; ++ctli )
  369.     {
  370.         if ( !ctl[ field ].first_four[ ctli ][ 0 ] ) break;
  371.         strncpy( four, ctl[num].first_four[ctli], 4 );
  372.         if ( four[3] == 'w' ) break;    /* w= no invert, no display
  373. */
  374.         fputs( four, fpo );
  375.         col= 4;
  376.         for ( i= low; i <= high; ++i)
  377.         {
  378.             if (( c= data_buf[i] ) == 037 ) /* begin sub-field */
  379.             {
  380.                 i++;    /* swallow next char    */
  381.                 if ( col <= 4 )
  382.                     continue;
  383.                 fputc( '\n', fpo );
  384.                 col= 0;
  385.                 continue;
  386.             }
  387. /*  ...If at end of sub-field or line getting too long, set for new
  388. line */
  389.             if ( c == 036 || ( col > 70 && isspace( c )) )
  390.             {
  391.                 fputc( '\n', fpo );
  392.                 col= 0;
  393.                 continue;
  394.             }
  395. /*  ...Swallow other non-printing characters, beginning semi-colon
  396. */
  397.             if ( !isprint( c ))
  398.                 continue;
  399.             if ( col == 4 && ( c == ';' || c == ' ' ))
  400.                 continue;
  401. /*  ...Prior to writing, set up lead 4 columns if needed    */
  402.             if ( col < 4 )
  403.             {
  404.                 fputs( "   ", fpo );
  405.                 fputc( four[3], fpo );
  406.                 col= 4;
  407.             }
  408.             if( c == ' ' )
  409.             {
  410.                 nxt = data_buf[i+1];
  411.                 if( nxt == ' ' || !isprint( nxt ) )
  412.                 continue;
  413.             }
  414.             fputc( c, fpo );
  415.             col++;
  416.         }
  417.     }
  418.     if( c == 035 )
  419.         fputc( '\n', fpo );
  420.     return;
  421. }
  422.